#include "ServerInfo.h"
#include <core/FileSys.h>
#include <qbtools/aess.h>
#include <QDomDocument> 
#include <QFile>
#include <QSettings>
#include <algorithm>

static const char* s_key = "www.sumscope.com";

QuoteServerInfo& QuoteServerInfo::instance()
{
	static QuoteServerInfo s_qsi;
	return s_qsi;
}

ServerInfo QuoteServerInfo::currentServer()
{
	ServerInfo si;
	bool found = false;
	for (auto g : m_serverGroups)
	{
		if (g.index == m_currentGroup)
		{
			for (auto server : g.servers)
			{
				if (server.index == m_currentServer)
				{
					si = server;
					found = true;
					break;
				}
			}
			break;
		}
	}
	if (!found && !m_serverGroups.empty() && !m_serverGroups[0].servers.empty())
		return m_serverGroups[0].servers[0];

	return si;
}

void QuoteServerInfo::updateUserInfo(const LoginUserInfo& v)
{
	m_loginUserInfo = v;
	saveConfig();
}

void QuoteServerInfo::updateProxyInfo(const ProxyInfo& v)
{
	m_proxyInfo = v;
//	m_proxyInfo.bUse = m_proxyInfo.nProxyType > kProxyBrowser;
	saveConfig();
}

QuoteServerInfo::QuoteServerInfo()
{
	loadConfig();
}

void QuoteServerInfo::loadConfig()
{
	//server
	QFile file(FileSys::instance()->appCfgDir() + "/ServerConfig.xml");
	while (true)
	{
		if(!file.open(QFile::ReadOnly))
			break;
		QDomDocument doc;
		if (!doc.setContent(&file))
		{
			file.close();
			return;
		}
		file.close();
		QDomElement root = doc.documentElement();
		QDomNodeList  nodeList = root.childNodes();
		for (int i = 0; i < nodeList.count(); ++i)
		{
			QDomElement node = nodeList.at(i).toElement();
			ServerGroup group;
			group.index = node.attribute("Index", "0").toInt();
			group.name = node.attribute("Name", "").toStdWString();
			group.en_name = node.attribute("EnName", "").toStdString();

			QDomNodeList serverList = node.childNodes();
			for (int j = 0; j < serverList.count(); ++j)
			{
				QDomElement server = serverList.at(j).toElement();
				ServerInfo si;
				si.index = server.attribute("Index", "0").toInt();
				QDomElement address = server.firstChildElement("Address");
				if (!address.isNull())
					si.address = address.text().toStdString();

				QDomElement port = server.firstChildElement("Port");
				if (!port.isNull())
					si.port = port.text().toInt();

				if (!si.address.empty() && si.port > 0)
					group.servers.push_back(si);
			}

			std::sort(group.servers.begin(), group.servers.end(), [](const ServerInfo& l, const ServerInfo& r) {
				return l.index < r.index;
				});
			m_serverGroups.push_back(group);
		}
		std::sort(m_serverGroups.begin(), m_serverGroups.end(), [](const ServerGroup& l, const ServerGroup& r) {
			return l.index < r.index;
			});

		break;
	}
	//user
	QSettings settings(FileSys::instance()->appCfgDir() + "/QuoteServer.ini", QSettings::IniFormat);
	settings.beginGroup("User");
	m_loginUserInfo.strUser = settings.value("Name", "").toString().toStdString();
	m_loginUserInfo.lastServerGroupIndex = settings.value("ServerGroup", 0).toInt();
	m_loginUserInfo.autoRun = settings.value("AutoLogin", "false").toBool();
	m_loginUserInfo.savePwd = settings.value("SavePasswd", "false").toBool();
	if (m_loginUserInfo.savePwd)
	{
		m_loginUserInfo.strPwd = settings.value("Passwd", "").toString().toStdString();
		m_loginUserInfo.strPwd = decryptPwd(m_loginUserInfo.strPwd);
	}
	
	settings.endGroup();

	settings.beginGroup("Proxy");
	m_proxyInfo.nProxyType = (ProxyType)settings.value("ProxyType", "0").toInt();
	m_proxyInfo.bUse = settings.value("ProxybUse", "false").toBool();
//	m_proxyInfo.bUse = m_proxyInfo.nProxyType > ProxyType::kProxyBrowser;
//	if (m_proxyInfo.bUse)
//	{
		m_proxyInfo.strProxyHost = settings.value("ProxyAddress", "").toString().toStdString();
		m_proxyInfo.nProxyPort = settings.value("ProxyPort", "").toInt();
		m_proxyInfo.strUsername = settings.value("ProxyUser", "").toString().toStdString();
		m_proxyInfo.strPassword = settings.value("ProxyPasswd", "").toString().toStdString();
		if (m_proxyInfo.strPassword != "")
		{
			m_proxyInfo.strPassword = decryptPwd(m_proxyInfo.strPassword);
		}
//	}
	settings.endGroup();
}

void QuoteServerInfo::saveConfig()
{
	QSettings settings(FileSys::instance()->appCfgDir() + "/QuoteServer.ini", QSettings::IniFormat);
	settings.beginGroup("User");
	settings.setValue("Name", QString::fromStdString(m_loginUserInfo.strUser));
	if(m_loginUserInfo.savePwd)
		settings.setValue("Passwd", encryptPwd(m_loginUserInfo.strPwd));
	settings.setValue("ServerGroup", m_loginUserInfo.lastServerGroupIndex);
	settings.setValue("AutoLogin", m_loginUserInfo.autoRun);
	settings.setValue("SavePasswd", m_loginUserInfo.savePwd);
	settings.endGroup();

	settings.beginGroup("Proxy");
	settings.setValue("ProxybUse", m_proxyInfo.bUse);
	settings.setValue("ProxyType", m_proxyInfo.nProxyType);
	settings.setValue("ProxyAddress", QString::fromStdString(m_proxyInfo.strProxyHost));
	settings.setValue("ProxyPort", m_proxyInfo.nProxyPort);
	settings.setValue("ProxyUser", QString::fromStdString(m_proxyInfo.strUsername));
	settings.setValue("ProxyPasswd", encryptPwd(m_proxyInfo.strPassword));
	settings.endGroup();
}

QString QuoteServerInfo::encryptPwd(const std::string& str)
{
	char* buffer = new char[2048];
	memset(buffer, 0, 2048);

	AES aes(s_key);
	int size = aes.DataEncrypt(str.c_str(), s_key, buffer, "");
	QString res;
	for (int i = 0; i < size; ++i)
	{
		res += QString("%1").arg((uchar)buffer[i], 2, 16, QChar('0'));
	}

	delete[] buffer;
	return res;
}

std::string QuoteServerInfo::decryptPwd(const std::string& str)
{
	char* pszData = new char[2048];
	memset(pszData, 0, 2048);

	char ch[3] = { 0 };
	int nLen = str.length();
	char* pszAsc = strdup(str.c_str());
	for (int i = 0; i < (nLen / 2); i++)
	{
		memcpy(ch, &pszAsc[i * 2], sizeof(char) * 2);
		if ((ch[0] >= '0') && (ch[0] <= '9'))
			pszData[i] = ch[0] - 0x30;
		else if ((ch[0] >= 'A') && (ch[0] <= 'F'))
			pszData[i] = ch[0] - 'A' + 10;
		else if ((ch[0] >= 'a') && (ch[0] <= 'f'))
			pszData[i] = ch[0] - 'a' + 10;
		else
			Q_ASSERT(0);

		pszData[i] *= 16;
		if ((ch[1] >= '0') && (ch[1] <= '9'))
			pszData[i] += ch[1] - 0x30;
		else if ((ch[1] >= 'A') && (ch[1] <= 'F'))
			pszData[i] += ch[1] - 'A' + 10;
		else if ((ch[1] >= 'a') && (ch[1] <= 'f'))
			pszData[i] += ch[1] - 'a' + 10;
		else
			Q_ASSERT(0);
	}
	if (pszAsc)free(pszAsc);

	AES aes(s_key);
	char* pszDecrypt = (char*)malloc(2000);
	memset(pszDecrypt, 0, sizeof(char) * 2000);
	std::string res;
	if (aes.DataDecrypt(pszData, s_key, pszDecrypt, "", (uint32_t)nLen / 2))
	{
		res = pszDecrypt;
	}


	delete[] pszData;
	free(pszDecrypt);
	return res;
}

void QuoteServerInfo::savepwd(str::string strpassword)
{
	//user
	QSettings settings(FileSys::instance()->appCfgDir() + "/QuoteServer.ini", QSettings::IniFormat);
	settings.beginGroup("User");
	m_loginUserInfo.savePwd = settings.value("SavePasswd", "false").toBool();
	if (m_loginUserInfo.savePwd)
	{
		m_loginUserInfo.strPwd = decryptPwd(strpassword);
	}
	
	settings.endGroup();
}

